{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "# Load environment variables from openai.env file\n",
    "load_dotenv(\"openai.env\")\n",
    "\n",
    "# Read the OPENAI_API_KEY from the environment\n",
    "api_key = os.getenv(\"OPENAI_API_KEY\")\n",
    "api_base = os.getenv(\"OPENAI_API_BASE\")\n",
    "os.environ[\"OPENAI_API_KEY\"] = api_key\n",
    "os.environ[\"OPENAI_API_BASE\"] = api_base"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 如何给agent正确的增加记忆\n",
    "\n",
    "- 将memory插入到提示词模板中\n",
    "<hr>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import Tool\n",
    "from langchain.agents import AgentType\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.utilities import SerpAPIWrapper\n",
    "from langchain.agents import initialize_agent\n",
    "from langchain.chains import LLMMathChain\n",
    "from langchain.prompts import  MessagesPlaceholder\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义大模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "llm=ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model=\"gpt-4-1106-preview\",\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "构建agent可用工具"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Tool(name='Search', description='useful for when you need to answer questions about current events or the current state of the world', func=<bound method SerpAPIWrapper.run of SerpAPIWrapper(search_engine=<class 'serpapi.google_search.GoogleSearch'>, params={'engine': 'google', 'google_domain': 'google.com', 'gl': 'us', 'hl': 'en'}, serpapi_api_key='f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594', aiosession=None)>), Tool(name='Calculator', description='useful for when you need to answer questions about math', func=<bound method Chain.run of LLMMathChain(verbose=True, llm_chain=LLMChain(prompt=PromptTemplate(input_variables=['question'], template='Translate a math problem into a expression that can be executed using Python\\'s numexpr library. Use the output of running this code to answer the question.\\n\\nQuestion: ${{Question with math problem.}}\\n```text\\n${{single line mathematical expression that solves the problem}}\\n```\\n...numexpr.evaluate(text)...\\n```output\\n${{Output of running the code}}\\n```\\nAnswer: ${{Answer}}\\n\\nBegin.\\n\\nQuestion: What is 37593 * 67?\\n```text\\n37593 * 67\\n```\\n...numexpr.evaluate(\"37593 * 67\")...\\n```output\\n2518731\\n```\\nAnswer: 2518731\\n\\nQuestion: 37593^(1/5)\\n```text\\n37593**(1/5)\\n```\\n...numexpr.evaluate(\"37593**(1/5)\")...\\n```output\\n8.222831614237718\\n```\\nAnswer: 8.222831614237718\\n\\nQuestion: {question}\\n'), llm=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x12e5a1410>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x12e5a2690>, model_name='gpt-4-1106-preview', temperature=0.0, openai_api_key='sk-pQ7osw5XrDY1Ejsx99EcEe5f58D04dDeB387B8E6B3C10bDb', openai_api_base='https://ai-yyds.com/v1', openai_proxy='https://ai-yyds.com/v1')), llm=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x12e5a1410>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x12e5a2690>, model_name='gpt-4-1106-preview', temperature=0.0, openai_api_key='sk-pQ7osw5XrDY1Ejsx99EcEe5f58D04dDeB387B8E6B3C10bDb', openai_api_base='https://ai-yyds.com/v1', openai_proxy='https://ai-yyds.com/v1'))>)]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/tomiezhang/.pyenv/versions/3.10.12/envs/langchains/lib/python3.11/site-packages/langchain/chains/llm_math/base.py:57: UserWarning: Directly instantiating an LLMMathChain with an llm is deprecated. Please instantiate with llm_chain argument or using the from_llm class method.\n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "os.environ[\"SERPAPI_API_KEY\"] = \"f265b8d9834ed7692cba6db6618e2a8a9b24ed6964c457296a2626026e8ed594\"\n",
    "#构建一个搜索工具\n",
    "search = SerpAPIWrapper()\n",
    "#创建一个数学计算工具\n",
    "llm_math_chain = LLMMathChain(\n",
    "    llm=llm,\n",
    "    verbose=True\n",
    ")\n",
    "tools = [\n",
    "    Tool(\n",
    "        name = \"Search\",\n",
    "        func=search.run,\n",
    "        description=\"useful for when you need to answer questions about current events or the current state of the world\"\n",
    "    ),\n",
    "    Tool(\n",
    "        name=\"Calculator\",\n",
    "        func=llm_math_chain.run,\n",
    "        description=\"useful for when you need to answer questions about math\"\n",
    "    ),\n",
    "]\n",
    "print(tools)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "增加memory组件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "#记忆组件\n",
    "memory = ConversationBufferMemory(\n",
    "    memory_key=\"chat_history\",\n",
    "    return_messages=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent_chain = initialize_agent(\n",
    "    tools, \n",
    "    llm, \n",
    "    agent=AgentType.OPENAI_FUNCTIONS, \n",
    "    verbose=True, \n",
    "    handle_parsing_errors=True,#处理解析错误\n",
    "    memory=memory #记忆组件\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "查看默认的agents prompt是什么样的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SystemMessage(content='You are a helpful AI assistant.'), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')]\n",
      "content='You are a helpful AI assistant.'\n",
      "prompt=PromptTemplate(input_variables=['input'], template='{input}')\n",
      "variable_name='agent_scratchpad'\n"
     ]
    }
   ],
   "source": [
    "print(agent_chain.agent.prompt.messages)\n",
    "print(agent_chain.agent.prompt.messages[0])\n",
    "print(agent_chain.agent.prompt.messages[1])\n",
    "print(agent_chain.agent.prompt.messages[2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m作为一个AI，我没有访问您个人信息的权限，所以我不知道您的名字。如果您愿意告诉我，我会知道如何称呼您。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'作为一个AI，我没有访问您个人信息的权限，所以我不知道您的名字。如果您愿意告诉我，我会知道如何称呼您。'"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_chain.run(\"我叫什么名字？\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "需要使用agent_kwargs传递参数，将chat_history传入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "agent_chain = initialize_agent(\n",
    "    tools, \n",
    "    llm, \n",
    "    agent=AgentType.OPENAI_FUNCTIONS, \n",
    "    verbose=True, \n",
    "    handle_parsing_errors=True,#处理解析错误\n",
    "    agent_kwargs={\n",
    "        \"extra_prompt_messages\":[MessagesPlaceholder(variable_name=\"chat_history\"),MessagesPlaceholder(variable_name=\"agent_scratchpad\")],\n",
    "    },\n",
    "    memory=memory #记忆组件\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "查看重新渲染后的提示词模版"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SystemMessage(content='You are a helpful AI assistant.'), MessagesPlaceholder(variable_name='chat_history'), MessagesPlaceholder(variable_name='agent_scratchpad'), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')]\n",
      "content='You are a helpful AI assistant.'\n",
      "variable_name='chat_history'\n",
      "variable_name='agent_scratchpad'\n"
     ]
    }
   ],
   "source": [
    "print(agent_chain.agent.prompt.messages)\n",
    "print(agent_chain.agent.prompt.messages[0])\n",
    "print(agent_chain.agent.prompt.messages[1])\n",
    "print(agent_chain.agent.prompt.messages[2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m作为一个文本交互的AI，我可以回顾我们的对话记录。到目前为止，我们的对话内容如下：\n",
      "\n",
      "1. 您问我：“我叫什么名字？”\n",
      "2. 我回答说，作为AI，我没有访问您个人信息的权限，所以我不知道您的名字，并提出如果您愿意告诉我，我会知道如何称呼您。\n",
      "\n",
      "这就是我们目前为止的全部对话内容。如果您有其他问题或需要帮助，请随时告诉我！\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'作为一个文本交互的AI，我可以回顾我们的对话记录。到目前为止，我们的对话内容如下：\\n\\n1. 您问我：“我叫什么名字？”\\n2. 我回答说，作为AI，我没有访问您个人信息的权限，所以我不知道您的名字，并提出如果您愿意告诉我，我会知道如何称呼您。\\n\\n这就是我们目前为止的全部对话内容。如果您有其他问题或需要帮助，请随时告诉我！'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_chain.run(\"好厉害，刚才我们都聊了什么？\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchains",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
             